package com.googlecode.cswish.model;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;

/**
 * Iterator element
 * 
 * @author Jerry.Feng Date: 2008-4-8
 */
public class ElementList extends AbstractList<PageElement> {
	// iterator the elements
	private int elementCursor;
	private int endCursor;
	// column cursor (0 ~ columnCount)
	private int columnCursor;
	private int columnCount;
	
	private List<PageElement> elements;
	
	public ElementList(List<PageElement> elements, int columnCount) {
		this.elements = elements;
		this.columnCount = columnCount;
		
		resetCursor(columnCount);
	}
	
	public boolean isLastelement() {
		return elementCursor == endCursor;
	}
	
	public boolean isFirstelement() {
		return elementCursor == 0;
	}
	
	public void resetCursor() {
		// default column count is 2
		resetCursor(2);
	}
	
	public void resetCursor(int columnCount) {
		this.columnCount = columnCount;
		elementCursor = -1;
		if (elements != null) {
			endCursor = elements.size() - 1;
		}
		columnCursor = -1;
	}
	
	/**
	 * The first line
	 * @return
	 */
	public boolean isFirstLine() {
		return elementCursor < columnCount;
	}
	
	/**
	 * The last line
	 * @return
	 */
	public boolean isLastLine() {
		return endCursor - elementCursor <= columnCount; 
	}
	
	/**
	 * The first element of one line
	 * 
	 * @return
	 */
	public boolean isFirstInLine() {
		return columnCursor == 0;
	}
	
	/**
	 * data in column
	 * 
	 * @param columnIndex
	 * @return
	 */
	public List<PageElement> getColumns(int columnIndex) {
		int len = elements.size();
		int maxColmnLen = len / columnCount + 1;
		List<PageElement> columns = new ArrayList<PageElement>(maxColmnLen);
		
		for (int i = columnIndex; i < len; i += columnCount) {
			columns.add(elements.get(i));
		}
		return columns;
	}
	
	public int getColumnCount() {
		return columnCount;
	}
	
	/**
	 * The last element of one line
	 * 
	 * @return
	 */
	public boolean isLastInLine() {
		/* isLastInLine <==>
		 * 1) no next element
		 * OR
		 * 2) the left space isn't enough for the next element
		*/
		boolean isLast = true;
		boolean hasNextelement = elementCursor < endCursor;
		if (hasNextelement) {
			int leftSpan = getLeftSpan();
			if (leftSpan > 0) { // leftSpan == 0 ==> requireSpan > 0 == true
				PageElement next = elements.get(elementCursor + 1);
				int requireSpan = next.getColspan();
				isLast = requireSpan > leftSpan;
			}
		}
		return isLast;
	}

	public int getLeftSpan() {
		return columnCount - columnCursor - getElement().getColspan();
	}
	
	public boolean next() {
		if (elementCursor == -1) {//firstly
			columnCursor = 0;
		} else {
			if (isLastInLine()) {// current element is the last one in the line
				columnCursor = 0;// the next element will be the first in the line 
			} else {
				// the move span equals the span of the previous element
				columnCursor += elements.get(elementCursor).getColspan();
			}
		}
		
		elementCursor++;		
		return elementCursor <= endCursor;
	}

	@Override
	public PageElement get(int index) {
		return elements.get(index);
	}
	
	public PageElement getElement() {
		if (elementCursor >= endCursor) {
			return elements.get(endCursor - 1);
		} else {
			return elements.get(elementCursor);
		}
	}

	@Override
	public int size() {
		return elements.size();
	}
}